using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace ImageCut
{
    /// <summary>
    /// 图像裁剪工具类，提供单张和批量图片裁剪功能
    /// </summary>
    public class ImageCropHelper
    {
        #region 裁剪结果类

        /// <summary>
        /// 裁剪结果信息
        /// </summary>
        public class CropResult
        {
            /// <summary>
            /// 原始文件路径
            /// </summary>
            public string OriginalFilePath { get; set; }

            /// <summary>
            /// 保存文件路径
            /// </summary>
            public string SavedFilePath { get; set; }

            /// <summary>
            /// 是否成功
            /// </summary>
            public bool Success { get; set; }

            /// <summary>
            /// 错误消息
            /// </summary>
            public string ErrorMessage { get; set; }

            /// <summary>
            /// 裁剪参数
            /// </summary>
            public CropParameters Parameters { get; set; }
        }

        /// <summary>
        /// 裁剪参数
        /// </summary>
        public class CropParameters
        {
            /// <summary>
            /// 裁剪起始X坐标
            /// </summary>
            public int X { get; set; }

            /// <summary>
            /// 裁剪起始Y坐标
            /// </summary>
            public int Y { get; set; }

            /// <summary>
            /// 裁剪宽度
            /// </summary>
            public int Width { get; set; }

            /// <summary>
            /// 裁剪高度
            /// </summary>
            public int Height { get; set; }

            /// <summary>
            /// JPEG质量（1-100，默认85）
            /// </summary>
            public long JpegQuality { get; set; } = 85;

            /// <summary>
            /// 参数验证
            /// </summary>
            public bool IsValid()
            {
                return X >= 0 && Y >= 0 && Width > 0 && Height > 0;
            }

            /// <summary>
            /// 获取参数字符串表示
            /// </summary>
            public override string ToString()
            {
                return $"({X},{Y},{Width},{Height})";
            }
        }

        /// <summary>
        /// 批量裁剪结果
        /// </summary>
        public class BatchCropResult
        {
            /// <summary>
            /// 成功数量
            /// </summary>
            public int SuccessCount { get; set; }

            /// <summary>
            /// 失败数量
            /// </summary>
            public int FailCount { get; set; }

            /// <summary>
            /// 详细结果列表
            /// </summary>
            public List<CropResult> Results { get; set; } = new List<CropResult>();

            /// <summary>
            /// 错误消息汇总
            /// </summary>
            public string ErrorSummary { get; set; }
        }

        #endregion

        #region 单张图片裁剪

        /// <summary>
        /// 裁剪单张图片
        /// </summary>
        /// <param name="sourceFilePath">源图片路径</param>
        /// <param name="parameters">裁剪参数</param>
        /// <param name="saveDirectory">保存目录</param>
        /// <param name="customFileName">自定义文件名（可选）</param>
        /// <returns>裁剪结果</returns>
        public static CropResult CropImage(string sourceFilePath, CropParameters parameters, 
            string saveDirectory, string customFileName = null)
        {
            var result = new CropResult
            {
                OriginalFilePath = sourceFilePath,
                Parameters = parameters
            };

            try
            {
                // 验证源文件
                if (!File.Exists(sourceFilePath))
                {
                    result.Success = false;
                    result.ErrorMessage = "源文件不存在";
                    return result;
                }

                // 验证参数
                if (!parameters.IsValid())
                {
                    result.Success = false;
                    result.ErrorMessage = "裁剪参数无效";
                    return result;
                }

                // 确保保存目录存在
                if (!Directory.Exists(saveDirectory))
                {
                    Directory.CreateDirectory(saveDirectory);
                }

                using (Bitmap original = new Bitmap(sourceFilePath))
                {
                    // 验证裁剪区域是否在图片范围内
                    if (parameters.X + parameters.Width > original.Width ||
                        parameters.Y + parameters.Height > original.Height)
                    {
                        result.Success = false;
                        result.ErrorMessage = $"裁剪区域超出图片范围 (图片尺寸: {original.Width}x{original.Height})";
                        return result;
                    }

                    // 执行裁剪
                    Bitmap croppedImage = CropBitmap(original, parameters);

                    // 生成保存路径
                    string fileName = string.IsNullOrEmpty(customFileName)
                        ? GenerateFileName(sourceFilePath, parameters)
                        : customFileName;

                    string savePath = Path.Combine(saveDirectory, fileName);

                    // 保存图片（优化压缩）
                    SaveOptimizedImage(croppedImage, savePath, sourceFilePath, parameters.JpegQuality);
                    croppedImage.Dispose();

                    result.Success = true;
                    result.SavedFilePath = savePath;
                }
            }
            catch (Exception ex)
            {
                result.Success = false;
                result.ErrorMessage = ex.Message;
            }

            return result;
        }

        /// <summary>
        /// 裁剪Bitmap对象
        /// </summary>
        /// <param name="source">源Bitmap</param>
        /// <param name="parameters">裁剪参数</param>
        /// <returns>裁剪后的Bitmap</returns>
        public static Bitmap CropBitmap(Bitmap source, CropParameters parameters)
        {
            Rectangle cropRect = new Rectangle(parameters.X, parameters.Y, 
                parameters.Width, parameters.Height);
            Bitmap croppedImage = new Bitmap(cropRect.Width, cropRect.Height);

            using (Graphics g = Graphics.FromImage(croppedImage))
            {
                g.DrawImage(source, new Rectangle(0, 0, croppedImage.Width, croppedImage.Height),
                    cropRect, GraphicsUnit.Pixel);
            }

            return croppedImage;
        }

        #endregion

        #region 批量图片裁剪

        /// <summary>
        /// 批量裁剪图片
        /// </summary>
        /// <param name="imageFiles">图片文件路径列表</param>
        /// <param name="parameters">裁剪参数</param>
        /// <param name="saveDirectory">保存目录</param>
        /// <returns>批量裁剪结果</returns>
        public static BatchCropResult BatchCropImages(List<string> imageFiles, 
            CropParameters parameters, string saveDirectory)
        {
            var batchResult = new BatchCropResult();
            string errorMessage = "";

            // 确保保存目录存在
            if (!Directory.Exists(saveDirectory))
            {
                Directory.CreateDirectory(saveDirectory);
            }

            foreach (string filePath in imageFiles)
            {
                var result = CropImage(filePath, parameters, saveDirectory);
                batchResult.Results.Add(result);

                if (result.Success)
                {
                    batchResult.SuccessCount++;
                }
                else
                {
                    batchResult.FailCount++;
                    errorMessage += $"{Path.GetFileName(filePath)}: {result.ErrorMessage}\n";
                }
            }

            batchResult.ErrorSummary = errorMessage;
            return batchResult;
        }

        /// <summary>
        /// 批量裁剪指定文件夹中的图片
        /// </summary>
        /// <param name="folderPath">文件夹路径</param>
        /// <param name="parameters">裁剪参数</param>
        /// <param name="saveDirectory">保存目录</param>
        /// <param name="searchPattern">搜索模式（如"*.jpg"）</param>
        /// <returns>批量裁剪结果</returns>
        public static BatchCropResult BatchCropFolder(string folderPath, 
            CropParameters parameters, string saveDirectory, string searchPattern = "*.jpg")
        {
            var imageFiles = new List<string>();

            if (Directory.Exists(folderPath))
            {
                imageFiles.AddRange(Directory.GetFiles(folderPath, searchPattern, 
                    SearchOption.TopDirectoryOnly));
            }

            return BatchCropImages(imageFiles, parameters, saveDirectory);
        }

        #endregion

        #region 辅助方法

        /// <summary>
        /// 优化保存图片（根据原始格式和质量参数）
        /// </summary>
        /// <param name="image">要保存的图片</param>
        /// <param name="savePath">保存路径</param>
        /// <param name="originalPath">原始文件路径</param>
        /// <param name="jpegQuality">JPEG质量（1-100）</param>
        private static void SaveOptimizedImage(Bitmap image, string savePath, string originalPath, long jpegQuality)
        {
            // 获取原始文件格式
            ImageFormat originalFormat = GetImageFormat(originalPath);
            
            // 如果是JPEG格式，使用压缩参数
            if (originalFormat.Equals(ImageFormat.Jpeg))
            {
                // 设置JPEG编码器参数
                ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
                EncoderParameters encoderParams = new EncoderParameters(1);
                encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, jpegQuality);
                
                image.Save(savePath, jpegCodec, encoderParams);
                encoderParams.Dispose();
            }
            else if (originalFormat.Equals(ImageFormat.Png))
            {
                // PNG格式保持无损
                image.Save(savePath, ImageFormat.Png);
            }
            else if (originalFormat.Equals(ImageFormat.Bmp))
            {
                // BMP转为JPEG以减小文件大小
                string newSavePath = Path.ChangeExtension(savePath, ".jpg");
                ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
                EncoderParameters encoderParams = new EncoderParameters(1);
                encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, jpegQuality);
                
                image.Save(newSavePath, jpegCodec, encoderParams);
                encoderParams.Dispose();
            }
            else
            {
                // 其他格式使用原格式保存
                image.Save(savePath, originalFormat);
            }
        }

        /// <summary>
        /// 获取图片格式
        /// </summary>
        private static ImageFormat GetImageFormat(string filePath)
        {
            string extension = Path.GetExtension(filePath).ToLower();
            switch (extension)
            {
                case ".jpg":
                case ".jpeg":
                    return ImageFormat.Jpeg;
                case ".png":
                    return ImageFormat.Png;
                case ".bmp":
                    return ImageFormat.Bmp;
                case ".gif":
                    return ImageFormat.Gif;
                default:
                    return ImageFormat.Jpeg; // 默认使用JPEG
            }
        }

        /// <summary>
        /// 获取图片编码器信息
        /// </summary>
        private static ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
            foreach (ImageCodecInfo codec in codecs)
            {
                if (codec.MimeType == mimeType)
                {
                    return codec;
                }
            }
            return null;
        }

        /// <summary>
        /// 生成带参数的文件名
        /// </summary>
        /// <param name="originalPath">原始文件路径</param>
        /// <param name="parameters">裁剪参数</param>
        /// <returns>新文件名</returns>
        private static string GenerateFileName(string originalPath, CropParameters parameters)
        {
            string fileName = Path.GetFileNameWithoutExtension(originalPath);
            string extension = Path.GetExtension(originalPath);
            return $"{fileName}{parameters}{extension}";
        }

        /// <summary>
        /// 验证裁剪参数是否适用于指定图片
        /// </summary>
        /// <param name="imagePath">图片路径</param>
        /// <param name="parameters">裁剪参数</param>
        /// <param name="errorMessage">错误消息</param>
        /// <returns>是否有效</returns>
        public static bool ValidateCropParameters(string imagePath, 
            CropParameters parameters, out string errorMessage)
        {
            errorMessage = "";

            if (!File.Exists(imagePath))
            {
                errorMessage = "图片文件不存在";
                return false;
            }

            if (!parameters.IsValid())
            {
                errorMessage = "裁剪参数无效（坐标必须>=0，宽高必须>0）";
                return false;
            }

            try
            {
                using (Bitmap image = new Bitmap(imagePath))
                {
                    if (parameters.X + parameters.Width > image.Width ||
                        parameters.Y + parameters.Height > image.Height)
                    {
                        errorMessage = $"裁剪区域超出图片范围 (图片尺寸: {image.Width}x{image.Height})";
                        return false;
                    }
                }
            }
            catch (Exception ex)
            {
                errorMessage = $"读取图片失败: {ex.Message}";
                return false;
            }

            return true;
        }

        /// <summary>
        /// 获取文件夹中的图片文件列表
        /// </summary>
        /// <param name="folderPath">文件夹路径</param>
        /// <param name="searchPattern">搜索模式</param>
        /// <returns>图片文件路径列表</returns>
        public static List<string> GetImageFiles(string folderPath, string searchPattern = "*.jpg")
        {
            var imageFiles = new List<string>();

            if (Directory.Exists(folderPath))
            {
                imageFiles.AddRange(Directory.GetFiles(folderPath, searchPattern, 
                    SearchOption.TopDirectoryOnly));
            }

            return imageFiles;
        }

        #endregion
    }
}
